#include "copyright.h"

#include "syscall.h"
#include "TicketTaker.h"


void finishedAgent(const char* name, int length){

	if(GetMonitor(ManagerFinishedName, ManagerFinishedNameLength, 0) == 1){
		ReleaseLock(name, length);
		Exit(1);
	}

}


int ticketTakerInitialize(){

	int myIndex;
	
	AcquireLock(ticketTakerIndexLockName, ticketTakerIndexLockNameLength);
		myIndex = GetMonitor(nextTicketTakerName, nextTicketTakerNameLength,0);
		SetMonitor(nextTicketTakerName, nextTicketTakerNameLength, myIndex + 1,0);
	ReleaseLock(ticketTakerIndexLockName, ticketTakerIndexLockNameLength);

	SetMonitor(ticketTakerLineCountName, ticketTakerLineCountNameLength, 0, myIndex);
	SetMonitor(ticketTakerStateName, ticketTakerStateNameLength, -1, myIndex);
				
	return myIndex;

}

void ticketTaker(){
	
	int myIndex;
	int tmp;
	
		myIndex = ticketTakerInitialize();
		

	while(1){
		/*printf("\t\t\tTT%i: about to acquire my ticket taker line lock\n", myIndex);*/
		/*Printing("TicketTaker %i\n", ConsoleOutput, myIndex, 0);*/
		/*Printing("TT %i trying to acquire lock at index %i\n", ConsoleOutput, myIndex, ticketTakerLineLock);*/
		AcquireLock(ticketTakerLineLockName, ticketTakerLineLockNameLength);  /* Look in line */
		/*Printing("TT %i acquired lock at index %i\n", ConsoleOutput, myIndex, ticketTakerLineLock);*/
		
		if(GetMonitor(ticketTakerLineCountName, ticketTakerLineCountNameLength,myIndex) > 0){
			/*printf("\t\t\tTT%i: Someone is in my line!\n", myIndex);*/
			Printing("TicketTaker %i has a line length %i and is signaling a customer.\n", ConsoleOutput, myIndex, GetMonitor(ticketTakerLineCountName, ticketTakerLineCountNameLength,myIndex));
			SetMonitor(ticketTakerStateName, ticketTakerStateNameLength, 1, myIndex);
			tmp = GetMonitor(ticketTakerLineCountName, ticketTakerLineCountNameLength, myIndex);
			SetMonitor(ticketTakerLineCountName, ticketTakerLineCountNameLength, tmp - 1, myIndex);
			/*ticketTakerLineCount[myIndex]--;*/
			Signal(ticketTakerLineConditionVariableName[myIndex], ticketTakerLineConditionVariableNameLength[myIndex], ticketTakerLineLockName, ticketTakerLineLockNameLength);
		} else {
			Printing("TicketTaker %i has no one in line. I am available for a customer.\n", ConsoleOutput, myIndex, 0);
			SetMonitor(ticketTakerStateName, ticketTakerStateNameLength,0,myIndex);
		}
		/*printf("\t\t\tTT%i: trying to acquire ticket taker lock\n", myIndex);*/
		AcquireLock(ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
		/*printf("\t\t\tTT%i: acquired ticket taker lock about to release ticket taker line lock\n", myIndex);*/
		ReleaseLock(ticketTakerLineLockName,ticketTakerLineLockNameLength);
		/*printf("\t\t\tTT%i: released ticket taker line lock, about to wait on my ticket taker lock\n", myIndex);*/
		Wait(ticketTakerConditionVariableName[myIndex], ticketTakerConditionVariableNameLength[myIndex], ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
		finishedAgent(ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
		/*printf("\t\t\tTT%i: reacquired my ticket taker lock\n", myIndex);*/
		
		if(GetMonitor(ticketTakerStateName, ticketTakerStateNameLength,myIndex) != 0){
			if(GetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength,myIndex) <= ROW_SIZE*NUM_ROWS - GetMonitor(numberAdmittedName, numberAdmittedNameLength, 0) && GetMonitor(movieStartTimeName, movieStartTimeNameLength, 0) == 0){
			/*if(ticketTakerCounter[myIndex] <= 10 - numberAdmitted && movieStartTime == 0){ testing purposes*/
				/* let them in */
				/*printf("\t\t\tTT%i: Youre good to go! Thanks brohan!\n", myIndex);*/
				
				Printing("TicketTaker %i has received %i tickets.\n", ConsoleOutput, myIndex, GetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength,myIndex));
				
				/*printf("\t\t\tTT%i: trying to acquire movie data lock\n", myIndex);*/
				AcquireLock(movieDataLockName, movieDataLockNameLength);
				/*printf("\t\t\tTT%i: acquired movie data lock\n", myIndex);*/
				tmp = GetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength, myIndex);
				SetMonitor(numberAdmittedName, numberAdmittedNameLength, GetMonitor(numberAdmittedName, numberAdmittedNameLength, 0) + tmp, 0);
				/*numberAdmitted += ticketTakerCounter[myIndex];*/
				
				Printing("TicketTaker %i is allowing the group into the theater. The number of tickets taken is %i.\n", ConsoleOutput, myIndex, GetMonitor(numberAdmittedName, numberAdmittedNameLength, 0));
				
				/*printf("\t\t\tTT%i: trying to release movie data lock\n", myIndex);*/
				ReleaseLock(movieDataLockName, movieDataLockNameLength);
				/*printf("\t\t\tTT%i: released movie data lock\n", myIndex);*/
				
				SetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength, 1, myIndex);
				
			} else {
				/* dont let them in */
				/*printf("\t\t\tTT%i: Sorry brochacho, cant let you in\n", myIndex);*/
				
				Printing("TicketTaker %i is not allowing the group into the theater. \0", ConsoleOutput, myIndex, GetMonitor(numberAdmittedName, numberAdmittedNameLength, 0));
				Printing("The number of taken tickets is %i and the group size is %i.\n", ConsoleOutput, GetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength,myIndex), 0);
				
				SetMonitor(ticketTakerCounterName, ticketTakerCounterNameLength, 0, myIndex);
				/*ticketTakerCounter[myIndex] = 0;*/
			}
		
			Signal(ticketTakerConditionVariableName[myIndex], ticketTakerConditionVariableNameLength[myIndex], ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
			/*printf("\t\t\tTT%i: Have a nice day!\n", myIndex);*/
			Wait(ticketTakerConditionVariableName[myIndex], ticketTakerConditionVariableNameLength[myIndex], ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
			finishedAgent(ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
		}
		
		AcquireLock(ticketTakerBreakLockName[myIndex], ticketTakerBreakLockNameLength[myIndex]);
		
		/*printf("\t\t\tTT%i: reacquired my ticket taker lock, about to release ticket taker lock\n", myIndex);*/
		ReleaseLock(ticketTakerLockName[myIndex], ticketTakerLockNameLength[myIndex]);
		/*printf("\t\t\tTT%i: released ticket taker lock, about to check for break stuff\n", myIndex);*/

		if(GetMonitor(ticketTakerBreakName, ticketTakerBreakNameLength,myIndex) == 1){ /* i should go on break */
			Printing("TicketTaker %i is going on break.\n", ConsoleOutput, myIndex, 0);
			/*AcquireLock(ticketTakerLineLock);*/
			/*ticketTakerLineCount[myIndex] = 0;*/
			/*Broadcast(ticketTakerLineConditionVariable[myIndex], ticketTakerLineLock);*/ /* signal to everyone in my line. need to acquire first???? */
			/*ReleaseLock(ticketTakerLineLock);*/
			Wait(ticketTakerBreakConditionVariableName[myIndex], ticketTakerBreakConditionVariableNameLength[myIndex], ticketTakerBreakLockName[myIndex], ticketTakerBreakLockNameLength[myIndex]); /* wait until I am off break */
			finishedAgent(ticketTakerBreakLockName[myIndex], ticketTakerBreakLockNameLength[myIndex]);
			Printing("TicketTaker %i is coming off break.\n", ConsoleOutput, myIndex, 0);
		}

		ReleaseLock(ticketTakerBreakLockName[myIndex], ticketTakerBreakLockNameLength[myIndex]);
	}
	
}

int main(){

	ticketTaker();

Exit(1);
}